package com.ayf.payment.game.api.service.payment.ayb;

import com.alibaba.fastjson.JSONObject;
import com.ayf.payment.game.api.bean.BaseResData;
import com.ayf.payment.game.api.dto.MerchantCommonDTO;
import com.ayf.payment.game.api.dto.MerchantConfigDTO;
import com.ayf.payment.game.api.dto.OrderAndMerchantDTO;
import com.ayf.payment.game.api.dto.OrderSplitDTO;
import com.ayf.payment.game.api.dto.ayb.SignPayProductDTO;
import com.ayf.payment.game.api.dto.platform.MerchantPaymentProductDTO;
import com.ayf.payment.game.api.dto.platform.PaymentChannelDTO;
import com.ayf.payment.game.api.entity.Order;
import com.ayf.payment.game.api.entity.Partition;
import com.ayf.payment.game.api.exception.NullSetException;
import com.ayf.payment.game.api.httpclient.HttpUtils;
import com.ayf.payment.game.api.service.MerchantRepository;
import com.ayf.payment.game.api.service.OrderService;
import com.ayf.payment.game.api.service.SignPayProductService;
import com.ayf.payment.game.api.service.payment.IPaymentService;
import com.ayf.payment.game.api.service.payment.ayb.util.AybSignUtil;
import com.ayf.payment.game.api.service.payment.util.PackageHtmlPayementFormUtil;
import com.ayf.payment.game.api.type.OrderStatus;
import com.ayf.payment.game.api.utils.BigDecimalUtil;
import com.ayf.payment.game.api.utils.DateUtils;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
public class AybPaymentService extends IPaymentService {

    @Autowired
    private SignPayProductService signPayProductService;

    @Resource
    private MerchantRepository merchantRepository;

    @Autowired
    private OrderService orderService;

    @Override
    public Map<String, Object> paymentUtil(Order order, Partition partition, String orderCreateStr, String traceId, String redirectUrl) {
        Map<String, Object> map=new HashMap<>();
        MerchantPaymentProductDTO merchantPaymentProductDTO = systemInitialization.productDTO(order.getPayTypeId());
        PaymentChannelDTO paymentChannelDTO = systemInitialization.channelDTO(merchantPaymentProductDTO.getcId());
        BigDecimal actualOrderAmt = getActualOrderAmt(order.getAmount(),paymentChannelDTO.getId(),partition.getMerchantId());
        MerchantCommonDTO merchantDTO = merchantService.getMerchantCommon(partition.getMerchantId());

        SignPayProductDTO signPayProduct=signPayProductService.getSignPayProductDTOByMId(partition.getMerchantId(),paymentChannelDTO.getCode());
        if (signPayProduct == null){
            throw new NullSetException(traceId + "当前商户未开通爱游宝支付，联系GM开通，享充值优惠");
        }
        if (signPayProduct.getCountSignPayProduct() == null || 0 == signPayProduct.getCountSignPayProduct()){
            throw new NullSetException(traceId + "当前商户未开通爱游宝支付，联系GM开通，享充值优惠");
        }
        if (signPayProduct.getApplyStatus() !=2){
            throw new NullSetException(traceId + "爱游宝支付申请未通过");
        }
        if (StringUtils.isEmpty(signPayProduct.getChannelMerchantId())){
            throw new NullSetException(traceId + "爱游宝支付通道商户号不存在");
        }

        List<Map<String,Object>> splitDetailsList = new ArrayList<>();
        MerchantConfigDTO merchantConfigDTO = merchantRepository.get(order.getMerchantId());
        BigDecimal merchantIncome;
        if (merchantConfigDTO.getMerchantType().equals("LOWER")) {
            BigDecimal rateLower = systemInitialization.proxyGroupSettleRateMap().get(merchantConfigDTO.getSettleIdentificationId()).get(order.getPayTypeId());
            merchantIncome = order.getAmount().multiply(rateLower.multiply(BigDecimal.valueOf(0.01)));
        } else {
            BigDecimal rateMerchant = systemInitialization.settleRateMap().get(merchantConfigDTO.getSettleIdentificationId()).get(order.getPayTypeId());
            merchantIncome = order.getAmount().multiply(rateMerchant.multiply(BigDecimal.valueOf(0.01)));
        }

        Map<String,Object> splitDetailMap = new HashMap<>();
        List<OrderSplitDTO> splitDTOList = new ArrayList<>();
        OrderSplitDTO orderSplitDTO = new OrderSplitDTO();
        orderSplitDTO.setMerchantId(String.valueOf(order.getMerchantId()));
        orderSplitDTO.setChannelMerchantId(signPayProduct.getChannelMerchantId());
        orderSplitDTO.setSplitAmt(merchantIncome);
        splitDTOList.add(orderSplitDTO);
        // GM商户号分账金额
        splitDetailMap.put("splitMerchantId",signPayProduct.getChannelMerchantId());
        splitDetailMap.put("splitAmt",String.valueOf(BigDecimalUtil.yuanToFen(merchantIncome)));
        splitDetailsList.add(splitDetailMap);

        BaseResData baseResData = orderCreate(traceId,order,paymentChannelDTO,redirectUrl,actualOrderAmt,merchantDTO,splitDetailsList);
        String orderCreateUrl = "";
        if (baseResData.isSuccess()) {
            orderCreateUrl = baseResData.getData();
            if (StringUtils.isEmpty(orderCreateUrl)){
                LogPortal.error("{} 商户ID[{}] 商户订单号[{}] 爱游宝下单失败 请求接口成功，接口返回报文 Data为空",traceId,order.getMerchantId(), order.getMerchantOrderNo());
                throw new NullSetException(traceId + "下单失败，请稍后重试！");
            }
        }
        LogPortal.info("{} 商户ID[{}] 商户订单号[{}] 爱游宝下单 通道支付URL[{}]", traceId, order.getMerchantId(), order.getMerchantOrderNo(),orderCreateUrl);
        order.setRandomAmt(BigDecimal.ZERO);
        order.setPayChannleName(paymentChannelDTO.getName());
        order.setPayChannleId(paymentChannelDTO.getId());
        order.setPayTypeId(merchantPaymentProductDTO.getProductId());
        order.setPayTypeName(merchantPaymentProductDTO.getProductName());
        order.setMerchantIncome(BigDecimal.ZERO);
        order.setPlatformIncome(BigDecimal.ZERO);
        order.setFee(BigDecimal.ZERO);
        order.setChannelIncome(BigDecimal.ZERO);
        order.setSplitFlag(1);
        order.setSplitDTOList(splitDTOList);
        orderService.saveOrder(order);
        map.put("code", "002");
        map.put("htmlMsg",orderCreateUrl);
        return map;
    }


    private BaseResData orderCreate(String traceId, Order order, PaymentChannelDTO paymentChannelDTO, String redirectUrl, BigDecimal actualOrderAmt,MerchantCommonDTO merchantDTO,List<Map<String,Object>> splitDetailsList){
        String methodName = "爱游宝下单";
        String KeyValue = paymentChannelDTO.getChannelKey();
        String parter = paymentChannelDTO.getAccountNumber();
        String returnUrl=paymentChannelDTO.getReturnUrl();
        String AuthorizationURL = paymentChannelDTO.getPaymentUrl();
        if (StringUtils.isEmpty(AuthorizationURL)){
            LogPortal.error("{} 失败，通道下单地址不能为空，订单号:{}",traceId,order.getMerchantOrderNo());
            throw new NullSetException(traceId + "下单失败，请稍后重试！");
        }
        if (!AuthorizationURL.endsWith("/")){
            AuthorizationURL=AuthorizationURL.concat("/");
        }
        if (StringUtils.isEmpty(returnUrl)){
            LogPortal.error("{} 失败，异步通知地址不能为空，订单号:{}",traceId,order.getMerchantOrderNo());
            throw new NullSetException(traceId + "下单失败，请稍后重试！");
        }
        if (!returnUrl.endsWith("/")){
            returnUrl=returnUrl.concat("/");
        }

        if (!redirectUrl.endsWith("/")){
            redirectUrl=redirectUrl.concat("/");
        }

        String qq = "";
        if (StringUtils.isNotBlank(merchantDTO.getCustomerQq())) {
            qq = merchantDTO.getCustomerQq();
        } else if (StringUtils.isNotBlank(merchantDTO.getQq())) {
            qq = merchantDTO.getQq();
        }

        String produceName = String.format("查单QQ:%s充值账号:%s订单号:%s",qq,order.getRechargeNumber(),order.getMerchantOrderNo());
        AuthorizationURL=AuthorizationURL.concat("ayb-pay-api/v1/cashier/pay/order/create");
        Map<String,String> reqParam = new LinkedHashMap<>();
        reqParam.put("merId",parter);
        reqParam.put("merchantOrderNo",order.getMerchantOrderNo());
        reqParam.put("orderAmount",String.valueOf(BigDecimalUtil.yuanToFen(actualOrderAmt)));// 单位：分
        reqParam.put("orderSubmitTime",DateUtils.dateToString(DateUtils.getNowDate(),DateUtils.formatPattern_full_01));
        reqParam.put("subject",produceName);
        reqParam.put("body",produceName);
        reqParam.put("notifyUrl",returnUrl.concat("gameapip/v/ayb/pay/notify"));
        reqParam.put("userIp",order.getClientIp());
        String sign= AybSignUtil.getSign(traceId,methodName,reqParam,KeyValue,paymentChannelDTO.getPlatformPrivateKey());
        reqParam.put("sign",sign);
        reqParam.put("partitionName",order.getPartitionName());
        reqParam.put("rechargeAccount",order.getRechargeNumber());
        reqParam.put("frontUrl",returnUrl.concat("gameapip/v/ayb/pay/returns"));
        reqParam.put("extra",redirectUrl);
        reqParam.put("splitDetails",JSONObject.toJSONString(splitDetailsList));

        BaseResData baseResData = new BaseResData();
        baseResData.setSuccess(true);
        baseResData.setData(PackageHtmlPayementFormUtil.packageHtmlPayementForm(reqParam,AuthorizationURL));
        return baseResData;
    }


    @Override
    public void queryPayOrder(OrderAndMerchantDTO dto, String traceId) {
        String methodDesc = "爱游宝订单查询";
        PaymentChannelDTO paymentChannelDTO = systemInitialization.channelDTO(dto.getPayChannleId());
        BaseResData baseResData = orderQuery(traceId,methodDesc,paymentChannelDTO,dto);
        if (baseResData.isProcessing()){
            return;
        }
        if (baseResData.isSuccess()){
            String result = baseResData.getData();
            JSONObject jsonRes = JSONObject.parseObject(result);
            int code = jsonRes.getIntValue("code");// 200 成功
            String ret_msg = jsonRes.getString("msg");
            if (200 == code){
                JSONObject jsonData = jsonRes.getJSONObject("data");
                //订单支付状态 INIT 订单初始化 PROCESSING 处理中 SUCCESS 成功 FAIL 失败
                String status = jsonData.getString("status");
                String merchantOrderNo = jsonData.getString("merchantOrderNo"); // 商户订单号
                String channelOrderNo = jsonData.getString("orderNo"); // 支付接口订单号
                Order order = orderService.selectByMerchantOrderNo(merchantOrderNo);
                if (order == null) {
                    LogPortal.error("{} {} 商户订单号[{}]在我方系统查询不到", traceId,methodDesc,merchantOrderNo);
                    return;
                }
                if (StringUtils.isEmpty(status) || "INIT".equals(status) || "PROCESSING".equals(status)){
                    LogPortal.error("{} {} 商户订单号[{}] 渠道返回状态不明确 返回状态:{}", traceId,methodDesc,merchantOrderNo,status);
                    return;
                }
                OrderStatus orderStatus= OrderStatus.PROCESSING;
                if ("SUCCESS".equals(status)){ // 成功
                    orderStatus= OrderStatus.SUCCESS;
                }
                if (OrderStatus.PROCESSING.equals(order.getOrderStatus()) && !orderStatus.equals(OrderStatus.PROCESSING)) {
                    order.setOrderStatus(orderStatus);
                    order.setChannelRpsMsg("支付成功");
                    if (StringUtils.isNotEmpty(channelOrderNo)){
                        order.setOrderNo(channelOrderNo);
                    }
                    orderService.paymentOrder(order, new JSONObject());
                    if (OrderStatus.SUCCESS.equals(order.getOrderStatus())) {
                        orderService.orderToGetWay(order);
                        wxSendMsgUtils.rechargeSuccess(order);
                    }
                }
            } else {
                LogPortal.error("{} {} 查询通道返回错误码:{} 错误描述:{}",traceId,methodDesc,code,ret_msg);
            }
        }
    }

    private BaseResData orderQuery(String traceId, String methodName, PaymentChannelDTO paymentChannelDTO, OrderAndMerchantDTO dto){
        String AuthorizationURL = paymentChannelDTO.getPaymentUrl();
        String orderNo = dto.getMerchantOrderNo();
        if (StringUtils.isEmpty(AuthorizationURL)){
            LogPortal.error("{} 失败，通道下单地址不能为空，订单号:{}",traceId,dto.getMerchantOrderNo());
            throw new NullSetException(traceId + "下单失败，请稍后重试！");
        }
        if (!AuthorizationURL.endsWith("/")){
            AuthorizationURL=AuthorizationURL.concat("/");
        }
        AuthorizationURL=AuthorizationURL.concat("ayb-pay-api/v1/api/pay/order/query");

        Map<String, String> reqParam = new LinkedHashMap<>();
        reqParam.put("partner",paymentChannelDTO.getAccountNumber());
        reqParam.put("merchantOrderNo",orderNo);
        String sign= AybSignUtil.getSign(traceId,methodName,reqParam,paymentChannelDTO.getChannelKey(),paymentChannelDTO.getPlatformPrivateKey());
        reqParam.put("sign",sign);
        BaseResData result = HttpUtils.sendPostForm(traceId,methodName,AuthorizationURL,reqParam);
        return result;
    }


    private static void testOrderCreate(){
        PaymentChannelDTO paymentChannelDTO = getTestPaymentChannelDTO();
        Order order = new Order();
        Date currentDate = DateUtils.getNowDate();
        String orderCreateStr = DateUtils.dateToString(currentDate, DateUtils.formatPattern_full_03);
        String orderNo = "M" + orderCreateStr + SnowFlakeUtils.getUniqueId();
        order.setMerchantOrderNo(orderNo);
        order.setCreateTime(currentDate);
        order.setAmount(BigDecimal.valueOf(1));
        order.setMerchantId(1000);
        String traceId = SnowFlakeUtils.getTraceId28();
        String redirectUrl = "http://uatxy.xyouplay.com";

        MerchantCommonDTO merchantCommonDTO = new MerchantCommonDTO();
        merchantCommonDTO.setCustomerQq("238948239");
        AybPaymentService xinYou2PaymentService = new AybPaymentService();
        BaseResData baseResData = xinYou2PaymentService.orderCreate(traceId,order,paymentChannelDTO,redirectUrl,order.getAmount(),merchantCommonDTO,null);
        System.out.println("爱游宝下单返回报文:"+JSONObject.toJSONString(baseResData));
    }

    private static PaymentChannelDTO getTestPaymentChannelDTO(){
        PaymentChannelDTO paymentChannelDTO = new PaymentChannelDTO();
        paymentChannelDTO.setPaymentUrl("http://t2www.aiyoboo.com");
        paymentChannelDTO.setReturnUrl("http://uatxy.xyouplay.com");
        paymentChannelDTO.setChannelKey("wejijweiuiewjwer");
        paymentChannelDTO.setAccountNumber("1001");// 商户ID
        return paymentChannelDTO;
    }

    public static void main(String[] args) {
        testOrderCreate();
    }

}
